package dryven.unittest;

import java.io.IOException;
import java.security.InvalidParameterException;

import dryven.util.crypt.AESDecryption;
import dryven.util.crypt.AESEncryption;
import dryven.util.crypt.AESGeneratedKey;
import dryven.util.crypt.MD5Hash;
import dryven.util.crypt.PasswordHash;
import dryven.util.crypt.RandomAlphaNumericalString;
import dryven.util.crypt.SHA1Hash;
import dryven.util.crypt.SHA256Hash;
import dryven.util.crypt.AESGeneratedKey.KeyLength;
import junit.framework.TestCase;

public class CryptUtilsTestCase extends TestCase {
	public void testHash() {
		String md5 = new MD5Hash("dryven").hash();
		//divide bitlength by 4 because hexadecimal strings contain 4 bits per byte
		assertEquals(128/4, md5.length());
		assertEquals("843C3E88B2A1B12FCBFBFBC367FEC29B",md5);
		String sha1 = new SHA1Hash("dryven").hash();
		assertEquals(160/4, sha1.length());
		assertEquals("2296EE7B69E3881040A3FC2C9FB18F17D5DC9B11",sha1);
		String sha256 = new SHA256Hash("dryven").hash();
		assertEquals(256/4, sha256.length());
		assertEquals("9384052268D40B35427C77A210FF3F99E345B65DBDCBCCAB17EBC59327B1FE7D",sha256);
	}
	
	public void testPasswordHash() {
		String pass = "dryven";
		String salt = "vDePYuKjiyptybFpxu7mcpX982dV42";
		PasswordHash h = new PasswordHash(pass,salt);
		assertEquals("3AD4D00BD5CDD4305D4996CA676144BC74D166D979D48E3FE469A18CAEB3E458",h.getHash());
		assertEquals(256/4, h.getHash().length());
		
		PasswordHash registeredPassword = new PasswordHash(pass);
		
		//hashes with different salts should not be equal
		assertTrue(!registeredPassword.getHash().equals(h.getHash()));
		
		PasswordHash loginPassword = new  PasswordHash(pass,registeredPassword.getSalt());
		//the hash should be the same for the same password and salt
		assertTrue(registeredPassword.getHash().equals(loginPassword.getHash()));
	}
	
	public void testKeyLength() {
		try {
			assertTrue(new AESGeneratedKey(KeyLength.AES128).getKey().length*8==128);
		} catch(InvalidParameterException e) {
			assertTrue(false);	//AES 128 must be supported
		}
		try {
			assertTrue(new AESGeneratedKey(KeyLength.AESHighestAvailable).getKey().length*8>=128);
		} catch(InvalidParameterException e) {
			assertTrue(false);	//AES 128 must be supported in highestavailable mode
		}
		try {
			assertTrue(new AESGeneratedKey(KeyLength.AES192).getKey().length*8==192);
		} catch(InvalidParameterException e) {}
		try {
			assertTrue(new AESGeneratedKey(KeyLength.AES256).getKey().length*8==256);
		} catch(InvalidParameterException e) {}
	}
	
	public void testRandomString() {
		String randomUpperCase = new RandomAlphaNumericalString(10, true).generate();
		assertEquals(randomUpperCase.length(), 10);
		assertEquals(randomUpperCase.toUpperCase(),randomUpperCase);
		String randomBothCases = new RandomAlphaNumericalString(10, false).generate();
		assertEquals(randomBothCases.length(), 10);
		
		String ss[] = new String[]{randomUpperCase,randomBothCases};
		for (String random : ss) {
			for (char c : random.toCharArray()) {
				assertTrue((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9'));
			}
		}
	}
	
	public void testAES() {
		AESGeneratedKey key = new AESGeneratedKey();
		String msg = "Let's see if AES encryption works, alright?";
		String encrypted = new AESEncryption(key, msg).encrypt();
		assertFalse(encrypted.equals(msg));
		String original = new AESDecryption(key, encrypted).decrypt();
		assertEquals(msg, original);
		//generated keys should be unique
		AESGeneratedKey key2 = new AESGeneratedKey();
		String encrypted2 = new AESEncryption(key2, msg).encrypt();
		assertFalse(encrypted.equals(encrypted2));
	}
}
